package com.netty.my;

import com.netty.http.HttpServerHandler;
import com.netty.utils.Constants;
import com.netty.utils.MongoDbUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.HttpConstants;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.multipart.*;
import io.netty.util.internal.PlatformDependent;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.io.File;

public class MyDefaultHttpDataFactory implements HttpDataFactory {


    public static final long MINSIZE = 16384L;
    public static final long MAXSIZE = -1L;
    private final boolean useDisk;
    private final boolean checkSize;
    private long minSize;
    private long maxSize;
    private Charset charset;
    private final Map<HttpRequest, List<HttpData>> requestFileDeleteMap;

    private HttpServerHandler httpServerHandler;

    public MyDefaultHttpDataFactory() {
        this.maxSize = -1L;
        this.charset = HttpConstants.DEFAULT_CHARSET;
        this.requestFileDeleteMap = PlatformDependent.newConcurrentHashMap();
        this.useDisk = false;
        this.checkSize = true;
        this.minSize = 16384L;
    }

    public MyDefaultHttpDataFactory(Charset charset) {
        this();
        this.charset = charset;
    }

    public MyDefaultHttpDataFactory(boolean useDisk) {
        this.maxSize = -1L;
        this.charset = HttpConstants.DEFAULT_CHARSET;
        this.requestFileDeleteMap = PlatformDependent.newConcurrentHashMap();
        this.useDisk = useDisk;
        this.checkSize = false;
    }


    public MyDefaultHttpDataFactory(long minSize, HttpServerHandler httpServerHandler) {
        this.maxSize = -1L;
        this.charset = HttpConstants.DEFAULT_CHARSET;
        this.requestFileDeleteMap = PlatformDependent.newConcurrentHashMap();
        this.useDisk = false;
        this.checkSize = true;
        this.minSize = minSize;
        this.httpServerHandler = httpServerHandler;
    }


    @Override
    public void setMaxLimit(long maxSize) {
        this.maxSize = maxSize;
    }

    private List<HttpData> getList(HttpRequest request) {
        List<HttpData> list = (List) this.requestFileDeleteMap.get(request);
        if (list == null) {
            list = new ArrayList();
            this.requestFileDeleteMap.put(request, list);
        }

        return (List) list;
    }

    @Override
    public Attribute createAttribute(HttpRequest request, String name) {
        List fileToDelete;
        if (this.useDisk) {
            Attribute attribute = new DiskAttribute(name, this.charset);
            attribute.setMaxSize(this.maxSize);
            fileToDelete = this.getList(request);
            fileToDelete.add(attribute);
            return attribute;
        } else if (this.checkSize) {
            Attribute attribute = new MixedAttribute(name, this.minSize, this.charset);
            attribute.setMaxSize(this.maxSize);
            fileToDelete = this.getList(request);
            fileToDelete.add(attribute);
            return attribute;
        } else {
            MemoryAttribute attribute = new MemoryAttribute(name);
            attribute.setMaxSize(this.maxSize);
            return attribute;
        }
    }

    @Override
    public Attribute createAttribute(HttpRequest request, String name, long definedSize) {
        List fileToDelete;
        if (this.useDisk) {
            Attribute attribute = new DiskAttribute(name, definedSize, this.charset);
            attribute.setMaxSize(this.maxSize);
            fileToDelete = this.getList(request);
            fileToDelete.add(attribute);
            return attribute;
        } else if (this.checkSize) {
            Attribute attribute = new MixedAttribute(name, definedSize, this.minSize, this.charset);
            attribute.setMaxSize(this.maxSize);
            fileToDelete = this.getList(request);
            fileToDelete.add(attribute);
            return attribute;
        } else {
            MemoryAttribute attribute = new MemoryAttribute(name, definedSize);
            attribute.setMaxSize(this.maxSize);
            return attribute;
        }
    }

    private static void checkHttpDataSize(HttpData data) {
        try {
            data.checkSize(data.length());
        } catch (IOException var2) {
            throw new IllegalArgumentException("Attribute bigger than maxSize allowed");
        }
    }

    @Override
    public Attribute createAttribute(HttpRequest request, String name, String value) {
        List fileToDelete;
        if (this.useDisk) {
            Object attribute;
            try {
                attribute = new DiskAttribute(name, value, this.charset);
                ((Attribute) attribute).setMaxSize(this.maxSize);
            } catch (IOException var6) {
                attribute = new MixedAttribute(name, value, this.minSize, this.charset);
                ((Attribute) attribute).setMaxSize(this.maxSize);
            }

            checkHttpDataSize((HttpData) attribute);
            fileToDelete = this.getList(request);
            fileToDelete.add(attribute);
            return (Attribute) attribute;
        } else if (this.checkSize) {
            Attribute attribute = new MixedAttribute(name, value, this.minSize, this.charset);
            attribute.setMaxSize(this.maxSize);
            checkHttpDataSize(attribute);
            fileToDelete = this.getList(request);
            fileToDelete.add(attribute);
            return attribute;
        } else {
            try {
                MemoryAttribute attribute = new MemoryAttribute(name, value, this.charset);
                attribute.setMaxSize(this.maxSize);
                checkHttpDataSize(attribute);
                return attribute;
            } catch (IOException var7) {
                throw new IllegalArgumentException(var7);
            }
        }
    }

    @Override
    public FileUpload createFileUpload(HttpRequest request, String name, String filename, String contentType, String contentTransferEncoding, Charset charset, long size) {
        if (size == 0) {
            size = Long.valueOf(httpServerHandler.parameter.get("fileLength").toString());
        }
        String tmpFileName = null;
        if (httpServerHandler.uploadTask != null) {
            //传过来的uploadId能找到记录，证明是断点续传
            tmpFileName = httpServerHandler.uploadTask.get("tmpFileName").toString();
        }

        List fileToDelete;
        MyDiskFileUpload fileUpload = new MyDiskFileUpload(name, filename, contentType, contentTransferEncoding, charset, size, httpServerHandler);
        if (!StringUtils.isEmpty(tmpFileName)) {
            File file = new File(MyDiskFileUpload.baseDirectory + tmpFileName);
            fileUpload.setFile(file);
        }
        fileUpload.setMaxSize(this.maxSize);
        checkHttpDataSize(fileUpload);
        fileToDelete = this.getList(request);
        fileToDelete.add(fileUpload);
        return fileUpload;
    }

    @Override
    public void removeHttpDataFromClean(HttpRequest request, InterfaceHttpData data) {
        if (data instanceof HttpData) {
            List<HttpData> fileToDelete = this.getList(request);
            fileToDelete.remove(data);
        }

    }

    @Override
    public void cleanRequestHttpData(HttpRequest request) {
        List<HttpData> fileToDelete = (List) this.requestFileDeleteMap.remove(request);
        if (fileToDelete != null) {
            Iterator var3 = fileToDelete.iterator();

            while (var3.hasNext()) {
                HttpData data = (HttpData) var3.next();
                data.delete();
            }

            fileToDelete.clear();
        }

    }

    @Override
    public void cleanAllHttpData() {
        Iterator i = this.requestFileDeleteMap.entrySet().iterator();

        while (true) {
            List fileToDelete;
            do {
                if (!i.hasNext()) {
                    return;
                }

                Map.Entry<HttpRequest, List<HttpData>> e = (Map.Entry) i.next();
                i.remove();
                fileToDelete = (List) e.getValue();
            } while (fileToDelete == null);

            Iterator var4 = fileToDelete.iterator();

            while (var4.hasNext()) {
                HttpData data = (HttpData) var4.next();
                data.delete();
            }

            fileToDelete.clear();
        }
    }

    @Override
    public void cleanRequestHttpDatas(HttpRequest request) {
        this.cleanRequestHttpData(request);
    }

    @Override
    public void cleanAllHttpDatas() {
        this.cleanAllHttpData();
    }


}
